/*
 * Copyright 2024 The JA-SIG Collaborative. All rights reserved.
 * distributed with thi file and available online at
 */
package com.lap.permission.service.impl;

import com.lap.framework.enums.YesNo;
import com.lap.permission.cachekey.MenuKey;
import com.lap.permission.cachekey.UserKey;
import com.lap.permission.convert.Convert;
import com.lap.permission.dal.MenuDAO;
import com.lap.permission.domain.entity.Menu;
import com.lap.permission.dto.response.MenuDTO;
import com.lap.permission.manager.MenuManager;
import com.lap.permission.service.MenuService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class MenuServiceImpl implements MenuService {

    private final MenuManager menuManager;

    private final MenuDAO menuDAO;

    private final Convert convert;

    @Cacheable(value = MenuKey.MENU_TREE, unless = "#result.isEmpty()")
    @Override
    public List<MenuDTO> queryTree() {
        return getTree(menuDAO.queryList());
    }

    @Cacheable(value = MenuKey.MENU_TREE_USER, key = "#userId", unless = "#result.isEmpty()")
    @Override
    public List<MenuDTO> queryByUserId(Integer userId) {
        return getTree(menuDAO.queryByUserId(userId));
    }

    private List<MenuDTO> getTree(List<Menu> list) {
        if (CollectionUtils.isEmpty(list))
            return Collections.emptyList();

        List<MenuDTO> sources = list.stream()
                .map(convert::toMenuDto)
                .toList();
        List<MenuDTO> result = sources.stream()
                .filter(menu -> YesNo.NO.getValue().equals(menu.getPid()))
                .sorted(Comparator.comparing(MenuDTO::getOrders))
                .toList();

        for (MenuDTO menu : result) {
            getResource(menu, sources, 0);
        }
        return result;
    }

    private MenuDTO getResource(MenuDTO parent, List<MenuDTO> sources, int dept) {
        log.debug("dept:::{}", dept);
        ++dept;
        if (dept >= 30)
            return parent;

        for (MenuDTO menu : sources) {
            if (parent.getId().equals(menu.getPid())) {
                List<MenuDTO> child = parent.getChildren();
                if (Objects.isNull(child)) {
                    child = new LinkedList<>();
                    parent.setChildren(child);
                }
                parent.getChildren().add(getResource(menu, sources, dept));
                Collections.sort(parent.getChildren());
            }
        }
        return parent;
    }

    @Override
    public Menu queryById(Integer menuId) {
        return menuDAO.queryById(menuId);
    }

    @Override
    public List<Menu> queryByPid(Integer parentId) {
        return menuDAO.queryByPid(parentId);
    }

    @CacheEvict(value = {MenuKey.MENU_TREE}, allEntries = true)
    @Override
    public Integer insertMenu(Menu menu) {
        menuDAO.insertMenu(menu);
        return menu.getId();
    }

    @CacheEvict(value = {MenuKey.MENU_TREE, MenuKey.MENU_TREE_USER}, allEntries = true)
    @Override
    public int updateMenu(Menu menu) {
        return menuDAO.updateMenu(menu);
    }

    @CacheEvict(value = {UserKey.USER_INFO, MenuKey.MENU_TREE, MenuKey.MENU_TREE_USER}, allEntries = true)
    @Override
    public int deleteById(Integer menuId) {
        return menuManager.deleteById(menuId);
    }

}
